/**
 * hw.h
 *
 *  Created on: 2018-05-11
 *      Author: chenshisheng
 */

#ifndef HW_H_
#define HW_H_

#include "main.h"

BEGIN_C_DECLS

#define HW_EXTI_FLAG_REALTIME  0x01

typedef enum
{
    HW_Level_Low = 0,
    HW_Level_High = 1
}HW_Level_t;

typedef enum
{
    HW_State_Inactive = 0,
    HW_State_Active =  1
}HW_State_t;

typedef enum
{
    HW_In_DIAG,

    HW_In_Max
}HW_In_t;

typedef enum
{
    HW_Out_Run,
    HW_Out_DIR,
    HW_Out_ENN,

    HW_Out_Max
} HW_Out_t;

typedef enum
{
    HW_Exti_DIAG,

    HW_Exti_Max
}HW_Exti_t;

typedef enum
{
    Hw_ExtiMode_Rising,
    Hw_ExtiMode_Falling,
    Hw_ExtiMode_BothEdge,
    Hw_ExtiMode_High,
    Hw_ExtiMode_Low,

    Hw_ExtiMode_Max
}Hw_ExtiMode_t;

void HW_Init(void);
void HW_Idle(void);
void HW_Resume(void);

void HW_Set(HW_Out_t out, HW_Level_t level);
HW_Level_t HW_GetSetted(HW_Out_t out);
void HW_Config(HW_Out_t out, HW_State_t status);
bool HW_IsConfigedActive(HW_Out_t out);
void HW_Toggle(HW_Out_t out);

HW_Level_t HW_Get(HW_In_t in);
bool HW_IsActive(HW_In_t in);

void HW_SetExtiCallback(HW_Exti_t exti, Callback_t cb, void *arg, unsigned int flags);
void HW_ExtiCmd(HW_Exti_t exti, bool enable);
void HW_SetExtiMode(HW_Exti_t exti, Hw_ExtiMode_t mode);

typedef struct
{
    GPIO_T *port;
    uint32_t bit;
}HW_t;

#define HW_MODE_OUTPUT GPIO_MODE_OUTPUT
#define HW_MODE_INPUT  GPIO_MODE_INPUT

typedef enum
{
	HW_Mode_OutputPushPull,
	HW_Mode_OutputOpenDrain,
	HW_Mode_Input,
	HW_Mode_Quasi,
}HW_Mode_t;

typedef enum
{
    HW_Pull_Disable,
    HW_Pull_Up,
    HW_Pull_Down,
}HW_Pull_t;

int HW_Pin_Init(const HW_t *hw, HW_Mode_t mode, HW_Pull_t pull);
void HW_SetSchmitInput(const HW_t *hw, bool isEnable);
void HW_SetHighSlewRate(const HW_t *hw, bool isEnable);

#define HW_STRUCT(io) {_PORT(io), _BIT(io)}
#define HW_PIN_INIT(hw, HW_Mode, HW_Pull) HW_Pin_Init(hw, HW_Mode, HW_Pull)

#define HW_SET(hw)   BIT_SET((hw)->port->DOUT, (hw)->bit)
#define HW_CLR(hw)   BIT_CLR((hw)->port->DOUT, (hw)->bit)
#define HW_GET(hw)   ((hw)->port->PIN & (hw)->bit ? 1 : 0)
#define HW_OUT(hw)   GPIO_SetMode((hw)->port, (hw)->bit, GPIO_MODE_OUTPUT)
#define HW_IN(hw)    GPIO_SetMode((hw)->port, (hw)->bit, GPIO_MODE_INPUT)
#define HW_DRAIN(hw) GPIO_SetMode((hw)->port, (hw)->bit, GPIO_MODE_OPEN_DRAIN)

END_C_DECLS
#endif /* HW_H_ */
